home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / drdobbs / 1991 / 02 / nelson / bitio.c < prev    next >
C/C++ Source or Header  |  1990-06-03  |  6KB  |  168 lines

  1. /*
  2.  * Listing 4 -- bitio.c
  3.  *
  4.  * This routine contains a set of bit oriented i/o routines
  5.  * used for arithmetic data compression.  The important fact to
  6.  * know about these is that the first bit is stored in the msb of
  7.  * the first byte of the output, like you might expect.
  8.  *
  9.  * Both input and output maintain a local buffer so that they only
  10.  * have to do block reads and writes.  This is done in spite of the
  11.  * fact that C standard I/O does the same thing.  If these
  12.  * routines are ever ported to assembly language the buffering
  13.  * will come in handy.
  14.  *
  15.  */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include "coder.h"
  19. #include "bitio.h"
  20.  
  21. #define BUFFER_SIZE 256
  22. static char buffer[ BUFFER_SIZE + 2 ]; /* This is the i/o buffer    */
  23. static char *current_byte;             /* Pointer to current byte   */
  24.  
  25. static int output_mask;                /* During output, this byte  */
  26.                                        /* contains the mask that is */
  27.                                        /* applied to the output byte*/
  28.                                        /* if the output bit is a 1  */
  29.  
  30. static int input_bytes_left;           /* During input, these three */
  31. static int input_bits_left;            /* variables keep track of my*/
  32. static int past_eof;                   /* input state.  The past_eof*/
  33.                                        /* byte comes about because  */
  34.                                        /* of the fact that there is */
  35.                                        /* a possibility the decoder */
  36.                                        /* can legitimately ask for  */
  37.                                        /* more bits even after the  */
  38.                                        /* entire file has been      */
  39.                                        /* sucked dry.               */
  40.  
  41.  
  42. /*
  43.  * This routine is called once to initialze the output bitstream.
  44.  * All it has to do is set up the current_byte pointer, clear out
  45.  * all the bits in my current output byte, and set the output mask
  46.  * so it will set the proper bit next time a bit is output.
  47.  */
  48. void initialize_output_bitstream()
  49. {
  50.     current_byte = buffer;
  51.     *current_byte = 0;
  52.     output_mask = 0x80;
  53. }
  54.  
  55. /*
  56.  * The output bit routine just has to set a bit in the current byte
  57.  * if requested to.  After that, it updates the mask.  If the mask
  58.  * shows that the current byte is filled up, it is time to go to the
  59.  * next character in the buffer.  If the next character is past the
  60.  * end of the buffer, it is time to flush the buffer.
  61.  */
  62. void output_bit( FILE *stream, int bit )
  63. {
  64.     if ( bit )
  65.         *current_byte |= output_mask;
  66.     output_mask >>= 1;
  67.     if ( output_mask == 0 )
  68.     {
  69.         output_mask = 0x80;
  70.         current_byte++;
  71.         if ( current_byte == ( buffer + BUFFER_SIZE ) )
  72.         {
  73.             fwrite( buffer, 1, BUFFER_SIZE, stream );
  74.             current_byte = buffer;
  75.         }
  76.         *current_byte = 0;
  77.     }
  78. }
  79.  
  80. /*
  81.  * When the encoding is done, there will still be a lot of bits and
  82.  * bytes sitting in the buffer waiting to be sent out.  This routine
  83.  * is called to clean things up at that point.
  84.  */
  85. void flush_output_bitstream( FILE *stream )
  86. {
  87.     fwrite( buffer, 1, (size_t)( current_byte - buffer ) + 1, stream );
  88.     current_byte = buffer;
  89. }
  90.  
  91. /*
  92.  * Bit oriented input is set up so that the next time the input_bit
  93.  * routine is called, it will trigger the read of a new block.  That
  94.  * is why input_bits_left is set to 0.
  95.  */
  96. void initialize_input_bitstream()
  97. {
  98.     input_bits_left = 0;
  99.     input_bytes_left = 1;
  100.     past_eof = 0;
  101. }
  102.  
  103. /*
  104.  * This routine reads bits in from a file.  The bits are all sitting
  105.  * in a buffer, and this code pulls them out, one at a time.  When the
  106.  * buffer has been emptied, that triggers a new file read, and the
  107.  * pointers are reset.  This routine is set up to allow for two dummy
  108.  * bytes to be read in after the end of file is reached.  This is because
  109.  * we have to keep feeding bits into the pipeline to be decoded so that
  110.  * the old stuff that is 16 bits upstream can be pushed out.
  111.  */
  112. short int input_bit( FILE *stream )
  113. {
  114.     if ( input_bits_left == 0 )
  115.     {
  116.         current_byte++;
  117.         input_bytes_left--;
  118.         input_bits_left = 8;
  119.         if ( input_bytes_left == 0 )
  120.         {
  121.             input_bytes_left = fread( buffer, 1, BUFFER_SIZE, stream );
  122.             if ( input_bytes_left == 0 )
  123.             {
  124.                 if ( past_eof )
  125.                 {
  126.                     fprintf( stderr, "Bad input file\n" );
  127.                     exit( -1 );
  128.                 }
  129.                 else
  130.                 {
  131.                     past_eof = 1;
  132.                     input_bytes_left = 2;
  133.                 }
  134.             }
  135.             current_byte = buffer;
  136.         }
  137.     }
  138.     input_bits_left--;
  139.     return ( ( *current_byte >> input_bits_left ) & 1 );
  140. }
  141.  
  142. /*
  143.  * When monitoring compression ratios, we need to know how many
  144.  * bytes have been output so far.  This routine takes care of telling
  145.  * how many bytes have been output, including pending bytes that
  146.  * haven't actually been written out.
  147.  */
  148. long bit_ftell_output( FILE *stream )
  149. {
  150.     long total;
  151.  
  152.     total = ftell( stream );
  153.     total += current_byte - buffer;
  154.     total += underflow_bits/8;
  155.     return( total );
  156. }
  157.  
  158. /*
  159.  * When monitoring compression ratios, we need to know how many bits
  160.  * have been read in so far.  This routine tells how many bytes have
  161.  * been read in, excluding bytes that are pending in the buffer.
  162.  */
  163. long bit_ftell_input( FILE *stream )
  164. {
  165.     return( ftell( stream ) - input_bytes_left + 1 );
  166. }
  167.  
  168.